/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "libzlang_stdtypes.h"

struct ZlangDirectProperty_bool
{
	unsigned char		value ;
} ;

ZlangInvokeFunction ZlangInvokeFunction_bool_FormatString_string;
int ZlangInvokeFunction_bool_FormatString_string( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bool	*obj_direct_prop = GetObjectDirectProperty(obj) ;
	struct ZlangObject		*in = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject		*out = GetOutputParameterInLocalObjectStack(rt,1) ;
	char				*format = NULL ;
	char				*bool_tostr = NULL ;
	int				fill_len ;
	char				*buf = NULL ;
	
	int				nret = 0 ;
	
	GetDataPtr( rt , in , (void**) & format , NULL );
	ReplaceChar( format , 'b' , 's' );
	
	if( obj_direct_prop->value == 1 )
		bool_tostr = ZLANG_OBJECT_bool_true ;
	else
		bool_tostr = ZLANG_OBJECT_bool_false ;
	
	fill_len = snprintf( NULL , 0 , format , bool_tostr ) ;
	buf = ZLMALLOC( fill_len+1 ) ;
	if( buf == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for bool str buf" )
		return ZLANG_ERROR_ALLOC;
	}
	sprintf( buf , format , bool_tostr );
	
	nret = FromCharPtr( rt , out , buf , fill_len ) ;
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "format\"%s\" bool_tostr\"%s\" -> formatting\"%s\"" , format , bool_tostr , buf )
	ZLFREE( buf );
	if( nret )
		return nret;
	
	return 0;
}

ZlangCreateDirectPropertyFunction ZlangCreateDirectProperty_bool;
void *ZlangCreateDirectProperty_bool( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bool	*bool_direct_prop = NULL ;
	
	bool_direct_prop = (struct ZlangDirectProperty_bool *)ZLMALLOC( sizeof(struct ZlangDirectProperty_bool) ) ;
	if( bool_direct_prop == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for entity" )
		return NULL;
	}
	memset( bool_direct_prop , 0x00 , sizeof(struct ZlangDirectProperty_bool) );
	
	return (void *)bool_direct_prop;
}

ZlangDestroyDirectPropertyFunction ZlangDestroyDirectProperty_bool;
void ZlangDestroyDirectProperty_bool( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bool	*bool_direct_prop = GetObjectDirectProperty(obj) ;
	
	ZLFREE( bool_direct_prop );
	
	return;
}

ZlangFromCharPtrFunction ZlangFromCharPtr_bool;
int ZlangFromCharPtr_bool( struct ZlangRuntime *rt , struct ZlangObject *obj , char *data_ptr , int32_t data_len )
{
	struct ZlangDirectProperty_bool	*bool_direct_prop = GetObjectDirectProperty(obj) ;
	
	if( data_len == 4 && STRNICMP( data_ptr , == , "true" , 4 ) )
	{
		bool_direct_prop->value = 1 ;
	}
	else if( data_len == 5 && STRNICMP( data_ptr , == , "false" , 5 ) )
	{
		bool_direct_prop->value = 0 ;
	}
	else
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_DATA_INVALID , "value invalid on from char ptr for bool" )
		return 1;
	}
	
	return 0;
}

ZlangToStringFunction ZlangToString_bool;
int ZlangToString_bool( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject **tostr_obj )
{
	struct ZlangDirectProperty_bool	*bool_direct_prop = GetObjectDirectProperty(obj) ;
	
	if( bool_direct_prop->value == 1 )
		CallRuntimeFunction_string_SetStringValue( rt , (*tostr_obj) , ZLANG_OBJECT_bool_true , sizeof(ZLANG_OBJECT_bool_true)-1 ) ;
	else
		CallRuntimeFunction_string_SetStringValue( rt , (*tostr_obj) , ZLANG_OBJECT_bool_false , sizeof(ZLANG_OBJECT_bool_false)-1 ) ;
	
	return 0;
}

ZlangFromDataPtrFunction ZlangFromDataPtr_bool;
int ZlangFromDataPtr_bool( struct ZlangRuntime *rt , struct ZlangObject *obj , void *value_ptr , int32_t value_len )
{
	struct ZlangDirectProperty_bool	*bool_direct_prop = GetObjectDirectProperty(obj) ;
	
	if( value_ptr )
	{
		bool_direct_prop->value = *((unsigned char *)value_ptr) ;
	}
	
	return 0;
}

ZlangGetDataPtrFunction ZlangGetDataPtr_bool;
int ZlangGetDataPtr_bool( struct ZlangRuntime *rt , struct ZlangObject *obj , void **value_ptr , int32_t *value_len )
{
	struct ZlangDirectProperty_bool	*bool_direct_prop = GetObjectDirectProperty(obj) ;
	
	if( value_ptr )
	{
		(*value_ptr) = & (bool_direct_prop->value) ;
	}
	
	if( value_len )
	{
		(*value_len) = sizeof(bool_direct_prop->value) ;
	}
	
	return 0;
}

ZlangUnaryOperatorFunction ZlangUnaryOperator_NOT_bool;
int ZlangUnaryOperator_NOT_bool( struct ZlangRuntime *rt , struct ZlangObject *in_out_obj1 )
{
	struct ZlangDirectProperty_bool	*in_out_1 = GetObjectDirectProperty(in_out_obj1) ;
	
	if( in_out_1->value == TRUE )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "![true]=>[false]" )
		in_out_1->value = FALSE ;
	}
	else
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "![false]=>[true]" )
		in_out_1->value = TRUE ;
	}
	
	return 0;
}

ZlangCompareFunction ZlangCompare_bool_EGUAL_bool;
int ZlangCompare_bool_EGUAL_bool( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject *out_obj )
{
	struct ZlangDirectProperty_bool	*in1 = GetObjectDirectProperty(in_obj1) ;
	struct ZlangDirectProperty_bool	*in2 = GetObjectDirectProperty(in_obj2) ;
	
	if( in1->value == in2->value )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "[%d]==[%d]=>[true]" , in1->value , in2->value )
		CallRuntimeFunction_bool_SetBoolValue( rt , out_obj , TRUE );
	}
	else
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "[%d]==[%d]=>[false]" , in1->value , in2->value )
		CallRuntimeFunction_bool_SetBoolValue( rt , out_obj , FALSE );
	}
	
	return 0;
}

ZlangCompareFunction ZlangCompare_bool_NOTEGUAL_bool;
int ZlangCompare_bool_NOTEGUAL_bool( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject *out_obj )
{
	struct ZlangDirectProperty_bool	*in1 = GetObjectDirectProperty(in_obj1) ;
	struct ZlangDirectProperty_bool	*in2 = GetObjectDirectProperty(in_obj2) ;
	
	if( in1->value != in2->value )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "[%d]!=[%d]=>[true]" , in1->value , in2->value )
		CallRuntimeFunction_bool_SetBoolValue( rt , out_obj , TRUE );
	}
	else
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "[%d]!=[%d]=>[false]" , in1->value , in2->value )
		CallRuntimeFunction_bool_SetBoolValue( rt , out_obj , FALSE );
	}
	
	return 0;
}

ZlangLogicFunction ZlangLogic_bool_AND_bool;
int ZlangLogic_bool_AND_bool( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject *out_obj )
{
	struct ZlangDirectProperty_bool	*in1 = GetObjectDirectProperty(in_obj1) ;
	struct ZlangDirectProperty_bool	*in2 = GetObjectDirectProperty(in_obj2) ;
	
	if( in1->value && in2->value )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "[%d]&&[%d]=>[true]" , in1->value , in2->value )
		CallRuntimeFunction_bool_SetBoolValue( rt , out_obj , TRUE );
	}
	else
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "[%d]&&[%d]=>[false]" , in1->value , in2->value )
		CallRuntimeFunction_bool_SetBoolValue( rt , out_obj , FALSE );
	}
	
	return 0;
}

ZlangLogicFunction ZlangLogic_bool_OR_bool;
int ZlangLogic_bool_OR_bool( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject *out_obj )
{
	struct ZlangDirectProperty_bool	*in1 = GetObjectDirectProperty(in_obj1) ;
	struct ZlangDirectProperty_bool	*in2 = GetObjectDirectProperty(in_obj2) ;
	
	if( in1->value || in2->value )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "[%d]||[%d]=>[true]" , in1->value , in2->value )
		CallRuntimeFunction_bool_SetBoolValue( rt , out_obj , TRUE );
	}
	else
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "[%d]||[%d]=>[false]" , in1->value , in2->value )
		CallRuntimeFunction_bool_SetBoolValue( rt , out_obj , FALSE );
	}
	
	return 0;
}

ZlangSummarizeDirectPropertySizeFunction ZlangSummarizeDirectPropertySize_bool;
void ZlangSummarizeDirectPropertySize_bool( struct ZlangRuntime *rt , struct ZlangObject *obj , size_t *summarized_obj_size , size_t *summarized_direct_prop_size )
{
	SUMMARIZE_SIZE( summarized_direct_prop_size , sizeof(struct ZlangDirectProperty_bool) )
	return;
}

static struct ZlangDirectFunctions direct_funcs_bool =
	{
		ZLANG_OBJECT_bool ,
		
		ZlangCreateDirectProperty_bool ,
		ZlangDestroyDirectProperty_bool ,
		
		ZlangFromCharPtr_bool ,
		ZlangToString_bool ,
		ZlangFromDataPtr_bool ,
		ZlangGetDataPtr_bool ,
		
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		
		NULL ,
		ZlangUnaryOperator_NOT_bool ,
		NULL ,
		NULL ,
		NULL ,
		
		ZlangCompare_bool_EGUAL_bool ,
		ZlangCompare_bool_NOTEGUAL_bool ,
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		
		ZlangLogic_bool_AND_bool ,
		ZlangLogic_bool_OR_bool ,
		
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		
		ZlangSummarizeDirectPropertySize_bool ,
	} ;

ZlangDirectFunction_bool_SetBoolValue bool_SetBoolValue;
int bool_SetBoolValue( struct ZlangRuntime *rt , struct ZlangObject *obj , unsigned char value )
{
	if( ! IsTypeOf( rt , obj , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
		return ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED;
	
	ZlangFromDataPtr_bool( rt , obj , & value , sizeof(unsigned char) );
	
	return 0;
}

ZlangDirectFunction_bool_GetBoolValue bool_GetBoolValue;
int bool_GetBoolValue( struct ZlangRuntime *rt , struct ZlangObject *obj , unsigned char *value )
{
	unsigned char	*v = NULL ;
	
	if( ! IsTypeOf( rt , obj , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
		return ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED;
	
	ZlangGetDataPtr_bool( rt , obj , (void**) & v , NULL );
	(*value) = (*v) ;
	
	return 0;
}

ZlangImportObjectFunction ZlangImportObject_bool;
struct ZlangObject *ZlangImportObject_bool( struct ZlangRuntime *rt )
{
	struct ZlangObject	*obj = NULL ;
	struct ZlangFunction	*func = NULL ;
	int			nret = 0 ;
	
	nret = ImportObject( rt , & obj , ZLANG_OBJECT_bool , & direct_funcs_bool , sizeof(struct ZlangDirectFunctions) , NULL ) ;
	if( nret )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_LINK_FUNC_TO_ENTITY , "import object to global objects heap" )
		return NULL;
	}
	
	/* bool.FormatString(...) */
	func = AddFunctionAndParametersInObject( rt , obj , "FormatString" , "FormatString(string)" , ZlangInvokeFunction_bool_FormatString_string , ZLANG_OBJECT_string , ZLANG_OBJECT_string,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	SetRuntimeFunction_bool_SetBoolValue( rt , bool_SetBoolValue );
	SetRuntimeFunction_bool_GetBoolValue( rt , bool_GetBoolValue );
	
	return obj ;
}

